package com.thbent.alarm.port;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.TooManyListenersException;

import javax.comm.CommPortIdentifier;
import javax.comm.PortInUseException;
import javax.comm.SerialPort;
import javax.comm.SerialPortEvent;
import javax.comm.SerialPortEventListener;
import javax.comm.UnsupportedCommOperationException;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class ReadSerialPort implements SerialPortEventListener {

	// SerialPortEventListener
	// 监听器,我的理解是独立开辟一个线程监听串口数据
	/* 检测系统中可用的通讯端口类 */
	static CommPortIdentifier portId; // 串口通信管理类
	static Enumeration<?> portList; // 有效连接上的端口的枚举
	InputStream inputStream; // 从串口来的输入流
	static OutputStream outputStream;// 向串口输出的流
	static SerialPort serialPort; // 串口的引用
	private static ReadSerialPort readSerialPort;
	private static final Logger LOGGER = LogManager.getLogger("ReadSerialPort");

	private ReadSerialPort() {

	}

	public static ReadSerialPort get() {
		if (null == readSerialPort) {
			readSerialPort = new ReadSerialPort();
			LOGGER.debug("创建串口对象" + readSerialPort);
		}
		return readSerialPort;
	}

	/**
	 * SerialPort EventListene 的方法,持续监听端口上是否有数据流
	 */
	@Override
	public void serialEvent(SerialPortEvent event) {
		// TODO Auto-generated method stub
		// System.out.println("事件接收信息");
		switch (event.getEventType()) {
		case SerialPortEvent.BI:// 通讯中断
		case SerialPortEvent.OE:// 溢位错误
		case SerialPortEvent.FE:// 帧错误
		case SerialPortEvent.PE:// 奇偶校验错
		case SerialPortEvent.CD:// 载波检测
		case SerialPortEvent.CTS:// 清除发送
		case SerialPortEvent.DSR:// 数据设备准备好
		case SerialPortEvent.RI:// 振铃指示
		case SerialPortEvent.OUTPUT_BUFFER_EMPTY:// 输出缓冲区已清空
			break;
		case SerialPortEvent.DATA_AVAILABLE:// 当有可用数据时读取数据

			// System.out.println("当有数据时读取数据");
			int a;
			try {
				while ((a = inputStream.read()) != -1) {
					// a = inputStream.read();
					System.out.print((char) (a));
				}
				System.out.println();

			} catch (IOException e) {
				// TODO Auto-generated catch block
				LOGGER.error(e.getMessage(), e);
			}
			break;
		}
	}

	/**
	 * 
	 * 通过程序打开COM4串口，设置监听器以及相关的参数
	 * 
	 * @return 返回1 表示端口打开成功，返回 0表示端口打开失败
	 */
	public int startComPort() {
		// 通过串口通信管理类获得当前连接上的串口列表
		portList = CommPortIdentifier.getPortIdentifiers();
		LOGGER.debug("有串口列表吗？？？？" + portList.hasMoreElements());
		while (portList.hasMoreElements()) {
			System.out.println(portList.hasMoreElements());
			// 获取相应串口对象
			portId = (CommPortIdentifier) portList.nextElement();

			System.out.println("设备类型dsx：--->" + portId.getPortType());
			System.out.println("设备名称：---->" + portId.getName());
			LOGGER.debug("设备类型：--->" + portId.getPortType());
			LOGGER.debug("串口号：---->" + portId.getName());
			// 判断端口类型是否为串口
			if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) {
				System.out.println("存在串口" + portId.getName());
				// 判断如果COM4串口存在，就打开该串口
				if (portId.getName().equals("COM4")) {
					try {
						// 打开串口名字为COM_4(名字任意),延迟为2毫秒
						serialPort = (SerialPort) portId.open("COM_4", 2000);

					} catch (PortInUseException e) {
						LOGGER.error(e.getMessage(), e);
						return 0;
					}
					// 设置当前串口的输入输出流
					try {
						inputStream = serialPort.getInputStream();
						outputStream = serialPort.getOutputStream();
					} catch (IOException e) {
						LOGGER.error(e.getMessage(), e);
						return 0;
					}
					// 给当前串口添加一个监听器
					try {
						serialPort.addEventListener(this);
					} catch (TooManyListenersException e) {
						LOGGER.error(e.getMessage(), e);
						return 0;
					}
					// 设置监听器生效，即：当有数据时通知
					serialPort.notifyOnDataAvailable(true);

					// 设置串口的一些读写参数
					try {
						// 比特率、数据位、停止位、奇偶校验位
						serialPort.setSerialPortParams(9600,
								SerialPort.DATABITS_8, SerialPort.STOPBITS_1,
								SerialPort.PARITY_NONE);
					} catch (UnsupportedCommOperationException e) {
						LOGGER.error(e.getMessage(), e);
						return 0;
					}
					System.out.println("start com ok");
					return 1;
				}
			}
		}

		return 0;

	}

	public void sendMessage(String message) {
		// StringBuffer unicode = new StringBuffer();
		// for (int i = 0; i < message.length(); i++) {
		// // 取出每一个字符
		// char c = message.charAt(i);
		// // ascii码范围外的全部转码
		// if (c >= 512) {
		// // 转换为unicode
		// unicode.append("\\u" + Integer.toHexString(c));
		// } else {
		// unicode.append(c);
		// }
		// }

		try {
			// System.out.println(unicode.toString()
			// + "**************************");
			// outputStream.write(unicode.toString().getBytes(), 0,
			// message.getBytes().length);
			char[] charArray = message.toCharArray();
			for (char c : charArray) {
				if (c >= 512) {
					byte[] GBKDecode = ("" + c).getBytes("gbk");
					for (byte b : GBKDecode) {
						outputStream.write(b);
					}
				} else {
					outputStream.write(c);
				}
			}
		} catch (IOException e) {
			LOGGER.error(e.getMessage(), e);
		}
	}

	public static String Chinese2GBK(String chineseStr) throws Exception {
		StringBuffer GBKStr = new StringBuffer();
		byte[] GBKDecode = chineseStr.getBytes("gbk");
		for (byte b : GBKDecode) {
			System.out.println(Integer.toHexString(b & 0xFF));
			GBKStr.append(Integer.toHexString(b & 0xFF));
		}
		return GBKStr.toString().toUpperCase();
	}

	public void sendMessage(int message) {
		try {
			outputStream.write(message);
		} catch (IOException e) {
			LOGGER.error(e.getMessage(), e);
		}
	}

}
